<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>geoip 库 ip 地址查询</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xmdhs/searchqanda/style.css">
    <script src="https://cdn.jsdelivr.net/npm/vue@3.2.21/dist/vue.global.js"></script>
</head>

<body>
    <div id="app">
        <div class="container-lg px-3 my-5 markdown-body">
            <h1>ip 地址查询</h1>
            <form id="getip" @submit.prevent="submit">
                <input type="search" id="ip" placeholder="1.1.1.1" name="ip" v-model.trim="ip">
                <input type="submit" value="查询">
            </form>
            <hr>
            <transition-group class="result" tag="div" name="list">
                <div class="card" v-for="{ip, result, id, spam} in resultList" :key="id">
                    <div class="card-body">
                        <span class="card-title">{{ ip }}</span>
                        <span class="card-text">{{ result.country || ""}}</span>
                        <span class="card-text">{{ result.region || ""}}</span>
                        <span class="card-text">{{ result.city || ""}}</span>
                        <span class="card-text isp">{{ result.isp || ""}}</span>
                        <span class="card-text">{{ result.ASN ? "AS" + result.ASN : "" }}</span>
                        <span class="card-text"><a href="https://www.spamhaus.org/" target="_blank">{{ spam || ""
                                }}</a></span>
                    </div>
                </div>
            </transition-group>
        </div>
    </div>
</body>

<script>
    Vue.createApp({
        setup() {
            const resultList = Vue.ref([]);
            const ip = Vue.ref("");
            const id = Vue.ref(0);

            /*
            127.0.0.2	SBL	Spamhaus SBL Data
            127.0.0.3	SBL	Spamhaus SBL CSS Data
            127.0.0.4	XBL	CBL Data
            127.0.0.9	SBL	Spamhaus DROP/EDROP Data (in addition to 127.0.0.2, since 01-Jun-2016)
            127.0.0.10	PBL	ISP Maintained
            127.0.0.11	PBL	Spamhaus Maintained
            */

            const _spamCode = {
                "127.0.0.2": "SBL",
                "127.0.0.3": "SBL",
                "127.0.0.4": "XBL",
                "127.0.0.9": "SBL",
                "127.0.0.10": "PBL",
                "127.0.0.11": "PBL",
                "127.255.255.252": "Typing error in DNSBL name",
            }
            function spamCode(code) {
                return _spamCode[code] || "Err code: " + code;
            }


            async function submit() {
                id.value = id.value + 1
                try {
                    let r = await fetch("https://auto.xmdhs.top:37981/ip/" + ip.value)
                    let result = await r.json()
                    if (r.status != 200) {
                        resultList.value.unshift({
                            ip: ip.value,
                            result: { isp: result.msg },
                            id: id.value
                        })
                        return
                    }

                    let ipl = ip.value.split(".")
                    let domain = ipl.reverse().join(".") + ".zen.spamhaus.org."
                    let rr = await fetch(`https://dns.alidns.com/resolve?name=${domain}&type=1`)

                    let rrj = await rr.json()
                    if (rr.status != 200) {
                        resultList.value.unshift({
                            ip: ip.value,
                            result: { isp: "查询失败" },
                            id: id.value
                        })
                        return
                    }
                    let spam = {}
                    rrj.Answer?.forEach(r => {
                        if (r.type == 1 && r.name == domain) {
                            spam[spamCode(r.data)] = true
                        }
                    })
                    let spams = Object.keys(spam).join(" ")
                    resultList.value.unshift({
                        ip: ip.value,
                        result: result,
                        id: id.value,
                        spam: spams
                    })
                } catch (e) {
                    resultList.value.unshift({
                        ip: ip.value,
                        result: { isp: e },
                        id: id.value
                    })
                    return
                }
            }

            return {
                ip: ip,
                resultList: resultList,
                id: id,
                submit
            }
        },
    }).mount('#app')
</script>

<style>
    .card {
        box-shadow: 0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%);
        border-radius: 10px;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
        font-size: 16px;
        line-height: 1.5;
        word-wrap: break-word;
        width: 100%;
        height: 100%;
        padding: 10px;
        box-sizing: border-box;
    }

    .card-body {
        display: flex;
        flex-wrap: wrap;
        column-gap: 5px;
        word-wrap: break-word;
    }

    .card-title {
        font-size: 24px;
        font-weight: bold;
        flex: 1 0 100%;
    }

    .isp {
        flex: 1 0 100%;
    }

    .result {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
        grid-gap: 10px;
    }

    .list-enter-active,
    .list-leave-active {
        transition: all 1s;
    }

    .list-enter-from,
    .list-leave-to {
        opacity: 0;
        transform: translateY(30px);
    }

    .list-move {
        transition: transform 0.8s;
    }
</style>

</html>